import logging
from event import WritableHandler, Event
from event_creator import EventCreator
from reactor import Reactor
from transport import Transport

log = logging

class Connector:
    class ConnectWritableHandler(WritableHandler):
        def __init__(self, connector):
            self.__connector = connector

        def write(self, event):
            if self.__connector is not None:
                self.__connector.transport().set_is_connected(True)
                self.__connector.on_connected()
            else:
                log.error("Connector(transport,reactor) is none")

    
    def __init__(self, transport, reactor):
        self.__transport = transport
        self.__reactor = reactor

    def on_connected(self):
        log.info("Transport Connected: trans:{}".format(self.__transport))

    def connect(self):
        try:
            self.__transport.connect()
        except BlockingIOError:
            ev = EventCreator.from_writable(self.__transport.handle(), Connector.ConnectWritableHandler(self))
            self.__reactor.register(ev)
        else:
            pass # log.error("")

        return self

    def reactor(self):
        return self.__reactor
    def transport(self):
        return self.__transport

class ConnectorWithArgs(Connector):
    def __init__(self, transport, reactor, handler=None, *args):
        super().__init__(transport, reactor)
        self.__handler = handler
        self.__args =args

    def on_connected(self):
        super().on_connected()
        if self.__handler is not None:
            self.__handler(*self.__args)
    



import unittest
class TestConnector(unittest.TestCase):
    #@unittest.skip('skip')
    def test_main(self):
        connector = Connector(Transport.from_tcp(), Reactor()).connect()

        thread = connector.reactor().loop_in_thread()

        import time 
        time.sleep(0.100)

        connector.reactor().loop_exit()

        connector.transport().disconnect()
        connector.transport().close()

        connector.reactor().loop_exit()

        thread.join()

    #@unittest.skip('skip')
    def test_callback_with_args(self):
        def callback(args):
            print(f"from connected-callback with:{args}")

        connector = ConnectorWithArgs(Transport.from_tcp(), Reactor(), callback, "hello").connect()

        thread = connector.reactor().loop_in_thread()

        import time 
        time.sleep(0.100)

        connector.transport().close()

        connector.reactor().loop_exit()

        thread.join()

    #@unittest.skip('skip')
    def test_callback_no_args(self):
        def callback():
            print(f"from connected-callback with no args")
        connector = ConnectorWithArgs(Transport.from_tcp(), Reactor(), callback).connect()

        thread = connector.reactor().loop_in_thread()

        import time 
        time.sleep(0.100)


        connector.transport().close()

        connector.reactor().loop_exit()

        thread.join()

        


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    unittest.main(verbosity=2)
